require"luaFDTD3D"
local nl = require"luaNumeric"
local plot = require "Q2DViewerEx"
require "unity"


-- require "Q2DViewer"
-- require "Q2DViewerEx"
-----------------------------------------------------------------------------
--初始化参数
local DataPost={
     nheader = 7;     
     data = {}; -- file to table
     str = {};   -- file to string   
   
     ------------------------------------------------------
     --所有数据，存储维度：1D
     --横坐标：索引，纵坐标：数值
     data_list = {};  --key：索引， value：数据
     ------------------------------------------------------
     
     ------------------------------------------------------
     --索引名称： 例如： { "freq", "theta" }
     keys = {};
     ------------------------------------------------------

     ------------------------------------------------------
     --每一个维度的数据
     --例如： { freq={1,2}, theta={0,180} }
     index = {};     --key: 名称, value: vector
     ------------------------------------------------------
     
     console = false;
};
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--创建表和创建元表
function DataPost:new (o)
	o = o or {};
	self.__index = self;	
	setmetatable(o,self)
	-- print( "RCSPost new" )
	return o;
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
function DataPost:print_labels( )
	for k,v in pairs(self.index) do
		print_table(v.label)
	end
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
function DataPost:print_data( )
	for k,v in pairs(self.data_list) do
		print(k.."="..v)
	end
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
function DataPost:get_key( idx )
	local ii = ""
	for k,v in pairs(idx) do
		ii = ii .. "  ".. v;
	end
	return ii;
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
function DataPost:sort_and_get_key( idx )
	local ii = ""
	-- print_table(idx)
	for k,v in pairs (self.keys) do
		-- print(k,v)
		ii = ii .. "  ".. idx[v];
	end
	return ii;
end
-----------------------------------------------------------------------------

function DataPost:read_from_file(path)				 
	print(path);
	self.data_list = {}
	self.data = file2table( path,"\t")	
	self.str = file2StrTable( path,"\t")	
	--print( self.str )
	local nheader = self.nheader;
	self.nangle = #self.str - nheader - 1 ;
	self.nfields = #self.str[nheader]-2;
	self.labels = self.str[nheader];
	
	number = "[ ]*[+-]?%d+[.]?%d*[Ee+-]*%d*";
	fields_type = '(.*)[%[(]';
	self.index = { theta = {labels={}, lable={}}, 
			     phi = {labels={}, lable={}}, 
			     freq = {labels={}, lable={}}, 
			     fields_types = {labels={}, lable={}}, };
	self.keys = {"theta","phi","freq","fields_types"};
	
	for jj=1,self.nfields do
		local label = self.labels[2+jj];
		local freq =  string.match(label, number)
		local fts = string.match(label, fields_type)
		table.insert( self.index["freq"].labels, freq); 
		table.insert( self.index["fields_types"].labels, fts); 
			
		for ii=1,self.nangle do
			local theta = self.data[ii+nheader+1][1];
			local phi = self.data[ii+nheader+1][2];
			local key = self:get_key({theta,phi,freq,fts})
			self.data_list[key] = self.data[ii+nheader+1][2+jj];
			table.insert( self.index["theta"].labels, theta); 
			table.insert( self.index["phi"].labels, phi); 
		end
	end
	
	assert( self.nangle>0, "import theta empty" )
	assert( self.nfields>0, "import theta empty" )
	
	print( "Import fields succesfully, angle size:".. self.nangle .. ' fields size:' .. self.nfields ..' data size:' .. #self.data_list );
	
	-- for k,v in pairs(self.data_list) do
		 -- print(k.."="..v)
	-- end 
	
	self:compress_idx();
	
	table.sort(self.index.theta.label,function (a,b) return tonumber(a)<tonumber(b) end )
	table.sort(self.index.phi.label,function (a,b) return tonumber(a)<tonumber(b) end )
	table.sort(self.index.freq.label,function (a,b) return tonumber(a)<tonumber(b) end )

end	

function Set(list)
	local set1 = {}
	for _,v in pairs(list) do set1[tostring(v)] = true; end
	
	local set2 = {}
	for k,v in pairs(set1) do table.insert( set2, k ); end
	return set2;
end

function DataPost:compress_idx()
	for k,v in pairs(self.index) do
		local idx = Set( v.labels );
		self.index[k].label = idx;
	end
end


function DataPost:clear_curves()
	assert(self.view, "You should creat a viewer first" )
	assert(self.mw:hasView(self.view)==true,"The viewer is closed!")
	self.mw:activeView(self.view);
	self.view:clearGraphs()
	self.view:rescaleAxes();
end



function maxn(t) 
	local n=0;
	for k,v in pairs(t) do
	     n = n+1;
	end
	return n;
end

-----------------------------------------------------------------------------
--col = { {label,data}, }
function grid( col, label, vals)
	local new_col = {};
	if #col == 0 then
	    col = { {label="", data={}} };
	end
	local ii=1;
	for k1,v1 in pairs (col) do
		local n = maxn(vals);
		for k2,v2 in pairs(vals) do
			new_col[ii] = {};
			new_col[ii].data = clone(v1.data);
			new_col[ii].data[label] = v2;
			new_col[ii].label = v1.label;
			if n>1 then
				new_col[ii].label = (v1.label or "") .. " " .. label .. "=" .. v2;
			end
			ii = ii+1;			
		end
	end
	return new_col;
end
-----------------------------------------------------------------------------


function DataPost:get_index()
	return self.index;
end

-----------------------------------------------------------------------------
--index = { name={}, }
--xAxis: name
function DataPost:plot_curves(xAxis,index)
	local xx,yys = self:get_curves(xAxis,index);
	for ii=1,#yys do 
		local gp = self.view:addGraph(xx,yys[ii].data,yys[ii].label)	    
	end
	self.view:rescaleAxes();

	if xAxis == "freq" then
		self:init_freq_spectrum_plot();
	end
	
	if xAxis == "theta" then
		self:init_angle_theta_spectrum_plot();
	end
	
	if xAxis == "phi" then
		self:init_angle_phi_spectrum_plot();
	end
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--index = { name={}, }
--xAxis: name
function DataPost:get_curves(xAxis,index)
	local xx = self.index[xAxis].label;
	local yys = {};
	local ydata = {};
	for k1,v1 in pairs(index) do
		ydata = grid(ydata, k1,v1 )
	end

	for ii=1,#ydata do
	     yys[ii] = {};
	     yys[ii].label = ydata[ii].label;
	     yys[ii].data = {};
	     
	     yidx = ydata[ii].data;
	     for jj=1,#xx do
		  yidx[xAxis] = xx[jj];
		  local idx = self:sort_and_get_key( yidx )
		  yys[ii].data[jj] = self.data_list[idx];
	     end
	end
	
	for k,v in pairs(xx) do
	    xx[k] = tonumber(v)
	end
	local   xx = nl.new_vector(xx)

	for ii=1,#yys do 
		yys[ii].data = nl.new_vector(yys[ii].data)
	end
	return xx, yys;
end
-----------------------------------------------------------------------------


function DataPost:create_view()
	if self.console~=true then
		local gallop = require "QGMainWindow"
		self.mw = gallop.getMainWindow();
		self.view = self.mw:create2DView("View2D");
	end
end

function DataPost:select_active_view()
	if self.console~=true then
		self.mw = gallop.getMainWindow();
		local view = self.mw:activeViewer2DChild();
		assert(self.mw:hasView(view)==true,"The active view is not a 2D viewer!")
		self.view = view;
	end
end

function DataPost:init_freq_spectrum_plot()
	 self.view.xAxis:setProperty( {name="频率 [GHz]"} )
	 self.view.yAxis:setProperty( {name="Fields [V/m]"} )
	 self.view:rescaleAxes();
end
function DataPost:init_angle_theta_spectrum_plot()
	 self.view.xAxis:setProperty( {name="方位角 θ [°]"} )
	 self.view.yAxis:setProperty( {name="Fields [V/m]"} )
	 self.view:rescaleAxes();
end

function DataPost:init_angle_phi_spectrum_plot()
	 self.view.xAxis:setProperty( {name="俯仰角 φ [°]"} )
	 self.view.yAxis:setProperty( {name="Fields [V/m]"} )
	 self.view:rescaleAxes();
end


return DataPost;


